/**
 *  Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com).
 *
 *  Licensed under the GPL, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.gnu.org/licenses/gpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.tinygroup.dbf.impl;

import org.tinygroup.dbf.DbfDataSet;
import org.tinygroup.dbf.DbfDocument;
import org.tinygroup.dbf.DbfField;
import org.tinygroup.dbf.DbfRecord;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Created by luoguo on 2014/7/10.
 */
public class StreamDbfDataSet implements DbfDataSet {

    private final FileChannel fileChannel;
    private final DbfDocument dbfDocument;
    private int position = 0;

    public StreamDbfDataSet(FileChannel fileChannel, DbfDocument dbfDocument) {
        this.fileChannel = fileChannel;
        this.dbfDocument = dbfDocument;
    }

    public void moveBeforeFirst() throws IOException {

    }

    public boolean next() {
        if (position >= dbfDocument.getHeader().getRecordCount()) {
            return false;
        }
        position++;
        return true;
    }

    public boolean absolute(int position) throws IOException {
        if (position >= dbfDocument.getHeader().getRecordCount()) {
            return false;
        }
        this.position = position;
        fileChannel.position(dbfDocument.getHeader().getHeaderLength() + (position - 1) * dbfDocument.getHeader().getRecordLength());
        return true;
    }

    protected void readByteBuffer(ByteBuffer byteBuffer) throws IOException {
        fileChannel.read(byteBuffer);
    }

    public DbfRecord getDbfRecord() throws IOException {

        ByteBuffer byteBuffer = ByteBuffer.allocate(1);
        readByteBuffer(byteBuffer);
        DbfRecord dbfRecord = new DbfRecord();

        dbfRecord.setDeleted((byteBuffer.array()[0] == '*'));
        for (DbfField field : dbfDocument.getFields()) {
            if (field.getType() == 'M' || field.getType() == 'B' || field.getType() == 'G') {
                throw new IOException("Not Support type Memo");
            }
            read(field, dbfRecord);
        }
        return dbfRecord;

    }

    private void read(DbfField field, DbfRecord dbfRecord) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(field.getLength());
        readByteBuffer(buffer);
        dbfRecord.getDataList().add(DbfUtil.getValue(new String(buffer.array(), dbfDocument.getEncode()).trim(), field));
    }

    public int getDbfRecordCount() {
        if (dbfDocument.getHeader() != null) {
            return dbfDocument.getHeader().getRecordCount();
        }
        return 0;
    }
}
